// 默认参数
import { DEFAULTS } from "./default.js";
// 工具函数
import { serialize, addURLData, serializeJson } from "./util.js";
// 常量
import {
  HTTP_GET,
  CONTENT_TYPE_FORM_URLENCODED,
  CONTENT_TYPE_JSON,
} from "./constants.js";
// Ajax类
class Ajax {
  constructor(url, options) {
    // 保存在this上就可以在类的其他方法中也可以使用url
    this.url = url;
    this.options = Object.assign({}, DEFAULTS, options);
    // 初始化
    this.init();
  }
  init() {
    const xhr = new XMLHttpRequest();
    this.xhr = xhr;
    // 绑定响应事件处理程序
    this.bindEvents();
    xhr.open(this.options.method, this.url + this.addParam(), true);
    this.setResponseType();
    this.setCookie();
    this.setTimeout();
    this.sendData();
  }
  bindEvents() {
    const xhr = this.xhr;
    const { success, httpCodeError, error, abort, timeout } = this.options;
    xhr.addEventListener(
      "load",
      () => {
        if (this.ok()) {
          success(xhr.response, xhr);
        } else {
          httpCodeError(xhr.status, xhr);
        }
      },
      false
    );
    xhr.addEventListener(
      "error",
      () => {
        error(xhr);
      },
      false
    );
    xhr.addEventListener(
      "abort",
      () => {
        abort(xhr);
      },
      false
    );
    xhr.addEventListener(
      "timeout",
      () => {
        timeout(xhr);
      },
      false
    );
  }
  // 检测响应HTTP状态码是否正常
  ok() {
    const xhr = this.xhr;
    return (xhr.status >= 200 && xhr.status < 300) || xhr.status === 304;
  }
  // 在地址上添加数据
  addParam() {
    const { params } = this.options;
    if (!params) return "";
    return addURLData(this.url, serialize(params));
  }
  // 设置请求数据类型
  setResponseType() {
    this.xhr.responseType = this.options.responseType;
  }
  // 是否设置Cookie
  setCookie() {
    if (this.options.withCredentials) {
      this.xhr.withCredentials = true;
    }
  }
  // 设置超时
  setTimeout() {
    const { timeoutTime } = this.options;
    if (timeoutTime > 0) {
      this.xhr.timeout = timeoutTime;
    }
  }
  sendData() {
    const xhr = this.xhr;
    const { data } = this.options;
    if (!this.isSendData()) {
      return xhr.send(null);
    }
    let resultData = null;
    // 是否发送formData格式数据
    if (!this.isformData()) {
      resultData = data;
    } else if (!this.isFormURLEncodedData()) {
      // 发送application/x-www-form-urlencoded格式的数据
      this.setContentTpye(CONTENT_TYPE_FORM_URLENCODED);
      resultData = serialize(data);
    } else if (!this.isJsonData()) {
      // 发送application/x-www-form-urlencoded格式的数据
      this.setContentTpye(CONTENT_TYPE_JSON);
      resultData = serializeJson(data);
    } else {
      this.setContentTpye();
      resultData = data;
    }
    return xhr.send(resultData);
  }
  // 是否需要使用send发送数据
  isSendData() {
    const { data, method } = this.options;
    if (!data) return false;
    if (method.toLowerCase() === HTTP_GET.toLowerCase()) return false;
    return true;
  }
  isformData() {
    return this.options.data instanceof FormData;
  }
  // 是否发送application/x-www-form-urlencoded格式的数据
  isFormURLEncodedData() {
    return this.options.contentType
      .toLowerCase()
      .includes(CONTENT_TYPE_FORM_URLENCODED);
  }
  // 是否发送application/json格式的数据
  isJsonData() {
    return this.options.contentType.toLowerCase().includes(CONTENT_TYPE_JSON);
  }
  // 设置Content-Type
  setContentTpye(contentType = this.options.contentType) {
    if (!contentType) return;
    this.xhr.contentType = contentType;
  }
  // 获取XHR对象
  getXHR() {
    return this.xhr;
  }
}

export { Ajax };
